Плохо! Плохо!:  0
Показано с 1 по 2 из 2

Тема: [MV / MZ] Туториал по Breakout-механике

  1. #1
    Бывалый Аватар для Darchan Kaen
    Информация о пользователе
    Регистрация
    17.06.2013
    Адрес
    Одесса
    Сообщений
    851
    Записей в дневнике
    3
    Репутация: 47 Добавить или отнять репутацию

    По умолчанию [MV / MZ] Туториал по Breakout-механике

    Туториал по Breakout-механике

    Версия 1.0 от 12.03.2022

    tl:dr, или "на что это похоже" в результате
    Спойлер Видео:




    Вступление
    Многие из вас, скорее всего, хотя-бы раз играли в игру Breakout. Это та игра, где нужно, управляя платформой, отбивать шарик и им разбивать блоки…вариаций этой игры довольно много.
    Но на мейкере, на MV/MZ, лично я реализации этой механики не видел (на VX Ace вроде бы есть)…что не показатель, конечно – но мне стало интересно, можно ли такое сделать? Без плагинов, чисто «на движке».
    Можно. Но с рядом существенных ограничений:
    1) Скорость игры (движения мяча) нельзя увеличить – (моя) реализация «ломается».
    2) Размер карты ограничен «полем зрения» игрока (что по-дефолту 17х13 тайлов) – возможное кол-во «блоков» относительно невилико, что может быть не так интересно.
    3) В случае использования «нескольких жизней», вывод сообщения о потере «жизни» замедляет темп игры.
    Недостаток №3 можно обойти плагинами на отображение переменных на экране (в демке выводится звук «вскрика»), а вот недостаток №1…Ну, может вы придумаете, как ускорить игру.
    Подчеркну, что логика игры не моя, а взята с официального туториала MDN, моя работа здесь – «подгон» логики под мейкер. Туториал доступен по ссылке:
    https://developer.mozilla.org/docs/G...ure_JavaScript

    Листинги скриптов будут доступны по ходу туториала, скриншотов не будет. Логика скриптов объясняется без деталей, детали в туториале по ссылке выше. Нужны скриншоты – качайте и открывайте демку. Номера переменных, переключателей, и звуки вы можете менять по своему усмотрению.

    Реализация
    0. Общие моменты
    Все цифровые значения, отличающиеся от туториала MDN, подобраны
    эмпирическим путем.
    Для реализации механики будет использоваться:
    А) Одно параллельное событие с четырьмя «листами»-страницами-вкладками. Также используется 5 переменных (дельтаX, дельтаY, кол-во блоков, кол-во жизней и доп. ширина игрока) и 2 переключателя (инициализация выполнена и не закончена ли игра) и много скриптов. Во всех скриптах нам важно знать ID события, являющегося мячом и ID событий, что являются блоками (ID первого блока и последнего)!!!

    Б) Один эвент, исполняющий роль «мяча» (эвент с нормальной скоростью и максимальной частотой!).

    В) Несколько (21) эвентов, исполняющие роль «блоков» для разбиения мячом; у каждого такого блока три листа – пустое базовое состояние, игровое состояние под локальным переключателем «A» и уничтоженное состояние без графики под локальным переключателем «B».

    Переменные дельтаX и дельтаY отвечают за «приращение» и изменение координат «мяча», кол-во блоков отвечает за конец игры, кол-во жизней – тоже, доп.ширина игрока – для удобства отбивания мяча, т.к. игрок по-умолчанию занимает 1 тайл.

    Конец игры наступает, или если уничтожены все блоки, или если у игрока 0 жизней; жизнь отнимается когда мяч достигает самой нижней линии экрана, что под игроком.

    1. Первый лист пареллельного эвента (Инициализация)
    В первой вкладке мы проводим инициализацию (подготовку) переменных для игры. А именно:
    1) Присваиваем переменным дельтаX и дельтаY значения: 1 и -1;
    2) Задаем кол-во блоков, кол-во жизней и доп. ширину игрока: 21 , 3 и 2 соответственно.
    3) Переводим блоки в игровое состояние, включая им всем локальный переключатель «A», при помощи скрипта:
    Спойлер Скрипт №1 (Страница 1):

    Код:
    let events = $gameMap.events();
    let beginIndex = 2;
    let endIndex = 24;
    for(let n = beginIndex; n < endIndex; n++){
    $gameSelfSwitches.setValue([$gameMap._mapId, n, 'A'], true);
    }

    4) Задаем игроку максимальную скорость – для удобства игры.
    5) Выключаем переключатель, сигнализирующий об окончании игры.
    6) Включаем переключатель, сигнализирующий что инициализация завершена.
    После шага 6) начинает работать второй лист пареллельного эвента.

    2. Второй лист параллельного эвента (Геймплей)
    Во второй вкладке происходит непосредственно контроль игрового
    процесса.
    Для реализации игрового процесса ставится цикл, где сначала идет
    пауза в 16 кадров, после выполняется ряд скриптов, после которых проверяется переменная с кол-вом блоков и, если блоков 0, цикл прерывается. После цикла включается переключатель, сигнализирующий об окончании игры.
    Пауза 16 кадров, как и свойства эвента-мяча (проходимость,
    нормальная скорость, максимальная частота) взяты не просто так. Если пауза меньше 16 кадров, то перемещение мяча отрисовывается слишком быстро (и он не долетает до границ экрана), если же скорость выше нормальной и/или частота не максимальная – отрисовывается дергано. Проходимость мяча опциональна, можно не ставить.
    Скрипты выполняются в определенной последовательности:
    1) Обрабатывается отскок мяча от блоков и их удаление.
    В данном скрипте проверяется совпадение координат мяча и блоков, и что блоки с которыми совпало не уничтожены, и в случае совпадения – блок «уничтожается». То есть у него активируется локальный переключатель «B», выключается «A», уменьшается кол-во блоков в переменной и проигрывается звук.
    И изменяется переменная дельтаY, чтоб мяч отпрыгивал под углом от уничтоженного блока!
    Спойлер Скрипт №2 (Страница 2):

    Код:
    let events = $gameMap.events(); let beginIndex = 2; let endIndex = 23;
    let ball = $gameMap.events().filter(event => event._eventId === 2)[0];
    for(let n = beginIndex; n < endIndex; n++){
    let currentBlockEvent = events[n];
    if( ball._x === currentBlockEvent._x && ball._y === currentBlockEvent._y && true === $gameSelfSwitches.value([$gameMap._mapId, events[n]._eventId, 'A']) ){
    $gameSelfSwitches.setValue([$gameMap._mapId, n+1, 'B'], true);
    $gameSelfSwitches.setValue([$gameMap._mapId, n+1, 'A'], false);
    let dy = $gameVariables.value(62); dy = -$gameVariables.value(62); $gameVariables.setValue(62, dy);
    let blocksCount = $gameVariables.value(63);blocksCount -= 1;
    $gameVariables.setValue(63, blocksCount); AudioManager.playSe({ name: 'Bell3', volume: 30, pitch: 100, pan: 0 });
    }
    }

    2) Обрабатывается отскок мяча от игрока.
    В данном скрипте проверяется совпадение координат мяча с координатами игрока (с учетом доп. ширины игрока из переменной) и, в случае совпадения, проигрывается звук.
    И изменяется переменная дельтаY, чтоб мяч отпрыгивал под углом от игрока!
    Спойлер Скрипт №3 (Страница 2):

    Код:
    let events = $gameMap.events(); let beginIndex = 2; let endIndex = 24;
    let ball = $gameMap.events().filter(event => event._eventId === 2)[0]
    let playerBonusWidth = $gameVariables.value(65);
    if( (ball._x >= ($gamePlayer._x - playerBonusWidth) && ball._x <= ($gamePlayer._x + playerBonusWidth) )
    && ball._y === $gamePlayer._y ){
    let dy = $gameVariables.value(62);
    dy = -$gameVariables.value(62);
    $gameVariables.setValue(62, dy);
    AudioManager.playSe({ name: 'Cursor2', volume: 30, pitch: 100, pan: 0 });
    }

    3) Обрабатывается контроль жизней (нахождения мяча «на дне» экрана).
    В данном скрипте проверяется совпадение вертикальной координаты (Y) мяч и, если она равна координате Y нижней линии экрана, от переменной жизней отнимается одна жизнь и проигрывается звук. Если жизней нет, включается переключатель, сигнализирующий об окончании игры (что автоматически разрывает цикл).
    Спойлер Скрипт №4 (Страница 2):

    Код:
    let events = $gameMap.events(); let beginIndex = 2; let endIndex = 24;
    let ball = $gameMap.events().filter(event => event._eventId === 2)[0];
    if(12 === ball._y){
    let lives = $gameVariables.value(64);
    lives -= 1;
    if(lives <= 0){
    $gameSwitches.setValue(62, true);
    }else{
    $gameVariables.setValue(64, lives);
    AudioManager.playSe({ name: 'Cry1', volume: 30, pitch: 100, pan: 0 });
    }
    }

    4) Обрабатывается отскок мяча от стен (и движения мяча вообще).
    В этом скрипте проверяется нахождение координат мяча в границах координат экрана (для каждой координаты отдельно) и, в случае если координаты выходят за границы, меняются переменные дельтаX и дельтаY (для отскока мяча от стен) и проигрывается звук. Также данный скрипт в принципе отвечает за перемещение мяча по экрану.
    Спойлер Скрипт №5 (Страница 2):

    Код:
    let ball = $gameMap.events().filter(event => event._eventId === 2)[0];
    let dx = $gameVariables.value(61);let dy = $gameVariables.value(62);
    if(ball._x + dx > 16 || ball._x + dx < 0) {
    dx = -$gameVariables.value(61); $gameVariables.setValue(61, dx);
    AudioManager.playSe({ name: 'Cursor1', volume: 30, pitch: 100, pan: 0 });
    }
    if(ball._y + dy > 12 || ball._y + dy < 0) {
    dy = -$gameVariables.value(62); $gameVariables.setValue(62, dy);
    AudioManager.playSe({ name: 'Cursor1', volume: 30, pitch: 100, pan: 0 });
    }
    dx = $gameVariables.value(61); dy = $gameVariables.value(62);
    ball._x += dx;ball._y += dy;

    Ну и потом условие кол-ва блоков, обрывающее цикл. В случае конца игры включается третья страница параллельного эвента.

    3. Третий лист параллельного эвента (Победа или Поражение)
    Не зависимо от того, уничтожены все блоки или нет, закончились жизни или нет – мы попадаем на эту вкладку. Вернее, ИЛИ блоки уничтожены, ИЛИ жизни кончились…Поэтому проверяем кол-во блоков условием мейкера, и если они уничтожены – пишем «Победа» и даем фанфары. Вместо этого можно проверять кол-во жизней – тут как кому удобно.
    В любом случае, после проверки условия и соответствующих действий, мы активируем локальный переключатель (например «D»…на всякий случай, он должен быть отличным от «A») и переходим на четвертую страницу эвента.

    4. Четвертый лист параллельного эвента (Пустой)
    Вкладка эвента пустая, тут ничего не происходит. Почему? Игра закончена!

    Заключение
    Надеюсь, сей краткий туториал был для вас полезен. И мы увидим еще больше мини-игр в проектах, всяких и разных. А может, вы еще и код скриптов улучшите – было бы круто…особенно в плане скорости движения мяча.
    Добавлю, что т.к. основная логика в параллельном эвенте, то все переменные и переключатели (и локальные переключатели блоков тоже) можно вернуть в стартовое значение и «перезапустить» таким образом игру. Но в туториале и демке это не показано.
    На этом серия моих «издевательств» на мукером, наверное, заканчивается…Ну, может я смогу сделать гонку когда-нибудь. В демке есть сразу все – и Breakout, и псевдо-«гравиган», и порталы.
    Ну и благодарю MDN за основной туториал, без которого данная реализация появилась бы значительно позже.

    Ссылки на загрузку демки (для MV, в ней же гравиган и порталы)
    Спойлер Ссылки, версия 1.0.0 от 12.03.2022:

    P.S:
    На MV и MZ все одинаково. В папке демки есть папки с pdf-туториалами.
    Последний раз редактировалось Darchan Kaen; 13.03.2022 в 00:24. Причина: Нет, нет, это не машина времени. Ни разу.

  2. #2
    Создатель Аватар для Рольф
    Информация о пользователе
    Регистрация
    14.04.2008
    Адрес
    Южно- Сахалинск/Пенза
    Сообщений
    10,146
    Записей в дневнике
    2
    Репутация: 108 Добавить или отнять репутацию

    По умолчанию

    Хорошая статья. Я люблю всякие не обычные реализации на мэйкере. Есть даже тема Мастера мэйера.

    п.с.
    https://rpgmaker.su/f25/%D0%9C%D0%B0...80%D0%B0-2451/

Информация о теме

Пользователи, просматривающие эту тему

Эту тему просматривают: 1 (пользователей: 0 , гостей: 1)

Метки этой темы

Социальные закладки

Социальные закладки

Ваши права

  • Вы не можете создавать новые темы
  • Вы не можете отвечать в темах
  • Вы не можете прикреплять вложения
  • Вы не можете редактировать свои сообщения
  •  
[MV / MZ] Туториал по Breakout-механике